{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Building prefix dict from the default dictionary ...\n",
      "Loading model from cache C:\\Users\\Administrator\\AppData\\Local\\Temp\\jieba.cache\n",
      "Loading model cost 0.495 seconds.\n",
      "Prefix dict has been built successfully.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TextRank算法关键词提取的结果：\n",
      "[('冰雪', 2.818580775017085), ('代表', 1.6769065531961425), ('字体', 1.664254690166437), ('书法', 1.5563854284163217), ('图形', 1.5442925688437703), ('形态', 1.4690250135581646), ('梦想', 1.417604933378319), ('出新', 1.4063687162110559), ('时代', 1.4012487452289446), ('运动员', 1.2952345207292995)]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\t\t\t\t\t\t\t\t#导入所需要的库与模块\n",
    "import jieba.posseg as pseg\n",
    "class TextRank(object):\t\t\t\t\t\t#定义TextRank类\n",
    "\tdef __init__(self, text, window, d, iters):\n",
    "\t\tself.text = text\n",
    "\t\tself.window = window\n",
    "\t\tself.d = d\n",
    "\t\tself.side_dict = {} \n",
    "\t\tself.iters = iters\n",
    "\t#构建节点集合\n",
    "\tdef get_nodes(self):\n",
    "\t\ttag_filter = ['a', 'd', 'n', 'v']\n",
    "\t\tcut_word = pseg.cut(self.text)\t\t\t#对文本进行分词\n",
    "\t\tfilter_list = [s.word for s in cut_word if s.flag in tag_filter]\n",
    "\t\tstop_word_path = 'data/stops_list.txt'\t#加载停用词表\n",
    "\t\tstopword_list = [sw.replace('\\n', '') for sw in open(stop_word_path, 'r', encoding = 'utf-8').readlines()]\n",
    "\t\tself.word_list = []\n",
    "\t\tfor word in filter_list:\n",
    "\t\t\tif not word in stopword_list and len(word) > 1:\n",
    "\t\t\t\tself.word_list.append(word)\n",
    "\t\twin_list = []\n",
    "\t\twlist_len = len(self.word_list)\n",
    "\t\t#遍历每个词，获取其索引和值\n",
    "\t\tfor index, word in enumerate(self.word_list):\n",
    "\t\t\t#判断词是否已经处理\n",
    "\t\t\tif word not in self.side_dict.keys(): \n",
    "\t\t\t\twin_list.append(word)\n",
    "\t\t\t\twin_set = set()\n",
    "\t\t\t\t#计算窗口的左边界和右边界\n",
    "\t\t\t\tleft = index - self.window + 1\n",
    "\t\t\t\tright = index + self.window\n",
    "\t\t\t\t#规范窗口边界，确保边界不会超出词表的范围\n",
    "\t\t\t\tif left < 0:\n",
    "\t\t\t\t\tleft = 0\n",
    "\t\t\t\tif right >= wlist_len:\n",
    "\t\t\t\t\tright = wlist_len\n",
    "\t\t\t\t#遍历窗口范围内的词\n",
    "\t\t\t\tfor i in range(left, right):\n",
    "\t\t\t\t\t#判断当前遍历的索引是否为当前词的索引\n",
    "\t\t\t\t\tif i == index:\n",
    "\t\t\t\t\t\tcontinue\n",
    "\t\t\t\t\telse:\t\t\t\t#将该词作为当前词的一个邻居\n",
    "\t\t\t\t\t\twin_set.add(self.word_list[i])\n",
    "\t\t\t\t#将当前词及其邻居存储在字典中\n",
    "\t\t\t\tself.side_dict[word] = win_set\n",
    "\tdef get_matrix(self):\t\t\t#构建一个表示无向图的邻接矩阵\n",
    "\t\t#初始化一个矩阵\n",
    "\t\tself.matrix = np.zeros([len(set(self.word_list)), len(set(self.word_list))])\n",
    "\t\tself.word_index = {}\n",
    "\t\tself.index_dict = {}\n",
    "\t\t#建立从词到索引的映射和从索引到词的映射\n",
    "\t\tfor i, v in enumerate(set(self.word_list)):\n",
    "\t\t\tself.word_index[v] = i\n",
    "\t\t\tself.index_dict[i] = v\n",
    "\t\tfor key in self.side_dict.keys():\t\t\t#构建无向图\n",
    "\t\t\tfor w in self.side_dict[key]:\n",
    "\t\t\t\t#建立无向边，有边为1，无边为0\n",
    "\t\t\t\tself.matrix[self.word_index[key]][self.word_index[w]] = 1\n",
    "\t\t\t\tself.matrix[self.word_index[w]][self.word_index[key]] = 1\n",
    "\tdef count_weight(self):\t\t\t\t\t\t\t#计算节点权重\n",
    "\t\tsum = np.sum(self.matrix, axis=0)\t\t\t#按列求和\n",
    "\t\t#遍历矩阵的每一个元素，将其除以相应列的和，实现每列的归一化。\n",
    "\t\tfor j in range(self.matrix.shape[1]):\n",
    "\t\t\tfor i in range(self.matrix.shape[0]):\n",
    "\t\t\t\tself.matrix[i][j] /= sum[j]\n",
    "\t\t#初始化一个全为1的向量\n",
    "\t\tself.node_vec = np.ones([len(set(self.word_list))])\n",
    "\t\tfor i in range(self.iters):\t\t\t\t#迭代更新\n",
    "\t\t\tself.node_vec = (1 - self.d) + self.d * np.dot(self.\n",
    "matrix, self.node_vec) \n",
    "\t\ttextR_dict = {}\n",
    "\t\tfor i in range(len(self.node_vec)):\n",
    "\t\t\ttextR_dict[self.index_dict[i]] = self.node_vec[i]\n",
    "\t\t#根据字典中的值进行降序排列\n",
    "\t\tres = sorted(textR_dict.items(), key = lambda x: x[1], reverse = True)\n",
    "\t\tprint('TextRank算法关键词提取的结果：')\n",
    "\t\tprint(res[:10])\n",
    "if __name__ == '__main__':\n",
    "\ttext = '冬奥会会徽以汉字“冬”为灵感来源，运用中国书法的艺术形态， 将厚重的东方文化底蕴与国际化的现代风格融为一体，呈现出新时代的中国新形象、新梦想，传递出新时代中国为办好北京冬奥会，圆冬奥之梦，实现“三亿人参与冰雪运动”目标，圆体育强国之梦，推动世界冰雪运动发展，为国际奥林匹克运动做出新贡献的不懈努力和美好追求。会徽图形上半部分展现滑冰运动员的造型，下半部分表现滑雪运动员的英姿。中间舞动的线条流畅且充满韵律，代表举办地起伏的山峦、赛场、冰雪滑道和节日飘舞的丝带，为会徽增添了节日喜庆的视觉感受，也象征着北京冬奥会将在中国春节期间举行。会徽以蓝色为主色调，寓意梦想与未来，以及冰雪的明亮纯洁。红黄两色源自中国国旗，代表运动的激情、青春与活力。在“BEIJING 2022”字体的形态上汲取了中国书法与剪纸的特点，增强了字体的文化内涵和表现力，也体现了与会徽图形的整体感和统一性。'\n",
    "\tTextRank = TextRank(text, 3, 0.85, 100)\n",
    "\tTextRank.get_nodes()\t\t\t\t\t\t#创建节点\n",
    "\tTextRank.get_matrix()\t\t\t\t\t\t#创建邻接矩阵\n",
    "\tTextRank.count_weight() \t\t\t\t\t#计算节点权重\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
